﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xeml.Document.Contracts;

namespace Xeml.Document.Ontologies.OBO
{
    class GeneralOboHandler : ContextLessHandler, IDynamicOntologyHandler
    {

        #region constructors
        public GeneralOboHandler()
            : base()
        {
        }

        public GeneralOboHandler(GeneralOboHandler other)
            : base()
        {
            InstanceLocation = other.InstanceLocation;
        }
        #endregion constructors

        #region IXemlComponent Members
        public string Publisher
        {
            get { return "Max Planck Institute of Molecular Plant Physiology, Potsdam/Golm, Germany"; }
        }

        private Version _version = new Version(1, 0, 0, 0);
        public Version Version
        {
            get { return _version; }
        }

        public new string ComponentName
        {
            get { return "General Ontology Handler"; }
        }

        public string Author
        {
            get { return "Kenny Billiau"; }
        }

        public string Description
        {
            get { return "Read in any obo file."; }
        }

        public string Uri
        {
            get { return InstanceLocation; }
        }

        public IXemlComponent Copy()
        {
            return new GeneralOboHandler(this);
        }
        #endregion

        protected override void DoTagTypeAnnotation(ParsedOboFile collection)
        {
            List<string> touchedTerms = new List<string>();

            var allIsARelations = collection.SelectMany(x => x.Where(y => y.Item1 == OboTags.is_a).Select(z => new { child = x.Id, is_a = z.Item2 })).OrderBy(x => x.is_a).ToList();

            var validChildTerms = collection.GetValidTags().Where(x => x.Any(OboTags.is_a)).Select(z => z.Id).Distinct().OrderBy(x => x).ToList();
            var rootAkaNoneChildTerms = collection.GetValidTags().Where(x => validChildTerms.BinarySearch(x.Id) < 0).Where(x => x.isHeaderTypeTerm);

            foreach (var item in rootAkaNoneChildTerms)
            {
                touchedTerms.Insert(0, item.Id);
                item.HeaderClass = OboTermClass.EnvironmentVariable;
            }

            int index = 0;
            bool altered = true;
            while (altered)
            {
                altered = false;
                foreach (var item in collection.AsParallel().AsUnordered().Where(x => x.isHeaderTypeTerm && x.isNoneTerm ))
                {
                    foreach (var is_a in item.Where(x => x.Item1 == OboTags.is_a))
                    {
                        index = touchedTerms.BinarySearch(is_a.Item2);
                        if (index >= 0)
                        {
                            index = touchedTerms.BinarySearch(item.Id);
                            if (index < 0)
                            {
                                item.HeaderClass = OboTermClass.EnvironmentVariable;
                                touchedTerms.Insert(~index, item.Id);
                            }
                            altered = true;
                        }
                    }
                }
            }
        }
    }
}